﻿using System;
using System.Collections.Generic;

namespace XTrace
{
	public abstract class XTraceListener : IDisposable
	{
		readonly List<XTraceSourcesBundle> _bundles = new List<XTraceSourcesBundle>();
		public IEnumerable<XTraceSourcesBundle> Bundles
		{
			get
			{
				lock (_bundles)
				{
					return _bundles.ToArray();
				}
			}
		}

		/// <summary>
		/// Create bundle from listener
		/// </summary>
		/// <param name="source"></param>
		public void AddBundle(XTraceSource source)
		{
			var oneToOne = new XTraceSourcesBundle();
			oneToOne.AddSource(source);
			AddBundle(oneToOne);
		}

		public void AddBundle(XTraceSourcesBundle bundle)
		{
			lock (_bundles)
			{
				if (!_bundles.Contains(bundle))
				{
					_bundles.Add(bundle);
					bundle.AddListener(this);
					lock (_listeners)
					{
						while (_listeners.Remove(this)) ;
					}
				}
			}
		}

		readonly static List<XTraceListener> _listeners = new List<XTraceListener>();

		public static IEnumerable<XTraceListener> Listeners
		{
			get
			{
				lock (_listeners)
				{
					return _listeners.ToArray();
				}
			}
		}

		public static void DisposeAndFlushAll()
		{
			XTraceListener[] lis;
			lock (_listeners)
			{
				lis = _listeners.ToArray();
			}
			foreach (var traceListener in lis)
			{
				traceListener.Dispose();
			}
			_listeners.Clear();
		}

		/// <summary>
		/// Register trace listener
		/// </summary>
		protected XTraceListener()
		{
			lock (_listeners)
			{
				_listeners.Add(this);
			}
		}

		public abstract void Event(XTraceEvent traceEvent);

		/// <summary>
		/// Unregister listener
		/// </summary>
		public void Dispose()
		{
			lock (_listeners)
			{
				_listeners.Remove(this);
			}
			DisposeImpl();
		}

		protected virtual void DisposeImpl()
		{
			
		}
	}
}
